"""
观察者Observer
被观察者Observable
观察者模式：是一种一对多的对象设计模式，一为被观察者，多为观察者。当被观察者发生改变时，观察者做出相应的改变
"""
from abc import ABCMeta, abstractmethod


class Observer(metaclass=ABCMeta):
    """
    观察者抽象类
    """
    @abstractmethod
    def update(self, observable, obj):
        pass


class Observable(object):
    """
    被观察者抽象类
    """

    def __init__(self):
        self.__observers = list()

    def append_observer(self, observer):
        self.__observers.append(observer)

    def remove_observer(self, observer):
        if observer in self.__observers:
            self.__observers.remove(observer)

    def notify(self, obj=0):
        for observer in self.__observers:
            observer.update(self, obj)


class WaterHeater(Observable):
    """
    热水器：洗澡模式 40<水温<60
           饮用模式 水温>=100
    """
    def __init__(self):
        super().__init__()
        self._temperature = 15

    def set_temperature(self, value):
        if 0 < value < 101:
            self._temperature = value
            print('当前水温是: %s摄氏度' % value)
        else:
            print('温度设置不合理')

        self.notify()

    def get_temperature(self):
        return self._temperature


class DrinkMode(Observer):
    """
    饮用模式
    """

    def update(self, observable, obj):
        current_temperature = observable.get_temperature()
        if current_temperature >= 100:
            print('水已经开了，可以放心饮用。')


class WashMode(Observer):
    """
    洗澡模式
    """
    def update(self, observable, obj):
        current_temperature = observable.get_temperature()

        if 40 < current_temperature < 60:
            print('水温合适，可以洗澡了。')


if __name__ == '__main__':
    # 热水器实例
    water_heater = WaterHeater()
    # 观察者实例
    drink = DrinkMode()
    wash = WashMode()
    water_heater.append_observer(drink)
    water_heater.append_observer(wash)
    water_heater.set_temperature(30)
    water_heater.set_temperature(50)
    water_heater.set_temperature(100)
